{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/laura/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "np.random.seed()\n",
    "# tf.set_random_seed()\n",
    "\n",
    "'''\n",
    "RNN linear is a net that tries to follow a circle with only linear components\n",
    "'''\n",
    "\n",
    "class RNN_linear():\n",
    "    def __init__(self, prediction_length = 40, batch_size = 1500, learning_rate = 0.01):           \n",
    "        \n",
    "        # Network variables\n",
    "        self.prediction_length = prediction_length\n",
    "        self.batch_size = batch_size\n",
    "        self.learning_rate = learning_rate\n",
    "        \n",
    "        # Placeholders for training\n",
    "        self.data_start = tf.placeholder(tf.float32, [None, 2])\n",
    "        self.data_true = tf.placeholder(tf.float32, [None, self.prediction_length, 2])\n",
    "            \n",
    "        ###############\n",
    "        # Given data_start, rotate in a circle at rate omega\n",
    "        ###############\n",
    "        init_state = self.data_start\n",
    "        \n",
    "        current_state = init_state\n",
    "        self.est_data_series = []\n",
    "        for num_pred in range(self.prediction_length):\n",
    "            # send state through the identity layer\n",
    "            layer_1 = tf.layers.dense(\n",
    "              init_state, 2, tf.identity, use_bias=True)\n",
    "            # set the next state to be current output\n",
    "            next_state = layer_1\n",
    "            # append next state to the est-data-series\n",
    "            self.est_data_series.append(next_state)\n",
    "            current_state = next_state\n",
    "\n",
    "#         self.est_data_series = tf.reshape(self.est_data_series,[batch_size,data_length,2])\n",
    "        self.est_data_series = tf.transpose(self.est_data_series, [1,0,2])\n",
    "        \n",
    "        ###############################################\n",
    "        # Define surrogate loss and optimization tensor\n",
    "        ###############################################\n",
    "        self.surr = tf.losses.mean_squared_error(self.est_data_series, self.data_true)\n",
    "        self.optimizer = tf.train.AdamOptimizer(self.learning_rate)\n",
    "        self.update_op = self.optimizer.minimize(self.surr)\n",
    "\n",
    "        ###############\n",
    "        # Start session\n",
    "        ###############\n",
    "        self.sess = tf.Session()\n",
    "        self.sess.run(tf.global_variables_initializer())\n",
    "            \n",
    "\n",
    "    def test_net(self, data_start, data_true):\n",
    "        \"\"\"\n",
    "        Test net function. Evaluates the session\n",
    "        \"\"\"\n",
    "\n",
    "        test_cost, test_est_series, test_mse_loss = self.sess.run([self.surr,self.est_data_series, \n",
    "                                                                   self.surr], \n",
    "                                                             feed_dict={\n",
    "                self.data_start: data_start,\n",
    "                self.data_true: data_true,\n",
    "                })\n",
    "        \n",
    "#         # save the weights from the layers\n",
    "#         with tf.variable_scope(\"identity_layer\", reuse=True):\n",
    "#             weights_1 = tf.get_variable(\"kernel\").eval(session = self.sess)\n",
    "#             bias_1 = tf.get_variable(\"bias\").eval(session = self.sess)\n",
    "                    \n",
    "        return (test_cost,test_est_series, test_mse_loss)#, weights_1, bias_1)\n",
    "    \n",
    "            \n",
    "    def train_net(self, data_start, data_true):\n",
    "        \"\"\"\n",
    "        Train net function. Calls self.update_op.\n",
    "        \"\"\"\n",
    "\n",
    "        _ , train_cost = self.sess.run([self.update_op, self.surr], feed_dict={\n",
    "                self.data_start: data_start,\n",
    "                self.data_true: data_true,\n",
    "                })\n",
    "        \n",
    "        return train_cost\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def data_generation(epochs, omega, data_length, batch_size):\n",
    "    \n",
    "    # create training data\n",
    "    import numpy as np\n",
    "    import scipy.signal as sig\n",
    "    from numpy import linalg as LA\n",
    "    import matplotlib.pyplot as plt\n",
    "\n",
    "    # Create training and test data for the NN\n",
    "\n",
    "    # number of random channels that will be trained and tested on\n",
    "    num_train=epochs*batch_size\n",
    "    num_test=batch_size\n",
    "\n",
    "    # QPSK\n",
    "    data_train = np.zeros((num_train, data_length,2))\n",
    "    data_test = np.zeros((num_test, data_length,2))\n",
    "    start_train = np.zeros((num_train, 2))\n",
    "    start_test = np.zeros((num_test, 2))\n",
    "\n",
    "    for i in range(num_train):\n",
    "        # first choose a random starting point on the unit circle\n",
    "        # there are 2pi radians in a circle, choose random number between 0 and 2pi\n",
    "        random_start = np.random.rand()*2*np.pi\n",
    "    #     random_start = 0\n",
    "        start_train[i,:] = np.array([np.cos(random_start), np.sin(random_start)])\n",
    "        # real part of data\n",
    "        data_train[i,0,:]=np.array([np.cos(random_start), np.sin(random_start)])\n",
    "\n",
    "        # rotate data according to omega\n",
    "        for j in range(1,data_length):\n",
    "            data_train[i,j,0]=(data_train[i,j-1,0]*np.cos(omega)-data_train[i,j-1,1]*np.sin(omega))\n",
    "            data_train[i,j,1]=(data_train[i,j-1,0]*np.sin(omega)+data_train[i,j-1,1]*np.cos(omega))\n",
    "\n",
    "        if i % 100000 == 0:\n",
    "            print(i)\n",
    "\n",
    "\n",
    "    for i in range(num_test):\n",
    "        # first choose a random starting point on the unit circle\n",
    "        # there are 2pi radians in a circle, choose random number between 0 and 2pi\n",
    "        random_start = np.random.rand()*2*np.pi\n",
    "    #     random_start = 0 \n",
    "        start_test[i,:]=np.array([np.cos(random_start), np.sin(random_start)])\n",
    "        # real part of data\n",
    "        data_test[i,0,:]=np.array([np.cos(random_start), np.sin(random_start)])\n",
    "\n",
    "        # rotate data according to omega\n",
    "        for j in range(1,data_length):\n",
    "            data_test[i,j,0]=(data_test[i,j-1,0]*np.cos(omega)-data_test[i,j-1,1]*np.sin(omega))\n",
    "            data_test[i,j,1]=(data_test[i,j-1,0]*np.sin(omega)+data_test[i,j-1,1]*np.cos(omega))\n",
    "\n",
    "    print(\"Data generation complete.\")\n",
    "    \n",
    "    return(data_train, data_test, start_train, start_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "100000\n",
      "Data generation complete.\n"
     ]
    }
   ],
   "source": [
    "epochs = 2000\n",
    "omega = 1/50\n",
    "data_length = 100\n",
    "batch_size = 100\n",
    "\n",
    "# generate the data\n",
    "(data_train, data_test, start_train, start_test) = data_generation(epochs, omega, data_length, batch_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fde64755dd8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "t = np.linspace(0,np.pi*2,100)\n",
    "plt.plot(np.cos(t), np.sin(t), linewidth=1, color='g')\n",
    "plt.gca().set_aspect('equal', adjustable='box')\n",
    "\n",
    "for j in range(0,data_length):\n",
    "    x = data_test[0,j,0]\n",
    "    y = data_test[0,j,1]\n",
    "    plt.plot(x,y,'bo')\n",
    "    \n",
    "# plt.plot(x1,y1,'bo')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Net trained on constant omega =  0.02\n",
      "Epoch 0, Train Cost 1.001015305519104, Test Cost: 0.9702341556549072, MSE Loss: 0.9702341556549072\n",
      "Epoch 100, Train Cost 0.17955127358436584, Test Cost: 0.17815503478050232, MSE Loss: 0.17815503478050232\n",
      "Epoch 200, Train Cost 0.028379803523421288, Test Cost: 0.026753565296530724, MSE Loss: 0.026753565296530724\n",
      "Epoch 300, Train Cost 0.0032280341256409883, Test Cost: 0.0031214419286698103, MSE Loss: 0.0031214419286698103\n",
      "Epoch 400, Train Cost 0.0002721586497500539, Test Cost: 0.0002596729318611324, MSE Loss: 0.0002596729318611324\n",
      "Epoch 500, Train Cost 1.5794947103131562e-05, Test Cost: 1.529331893834751e-05, MSE Loss: 1.529331893834751e-05\n",
      "Epoch 600, Train Cost 6.54186976589699e-07, Test Cost: 6.246367547646514e-07, MSE Loss: 6.246367547646514e-07\n",
      "Epoch 700, Train Cost 1.711434727269534e-08, Test Cost: 1.6715077322260186e-08, MSE Loss: 1.6715077322260186e-08\n",
      "Epoch 800, Train Cost 3.11982273348832e-10, Test Cost: 3.073704346601147e-10, MSE Loss: 3.073704346601147e-10\n",
      "Epoch 900, Train Cost 3.781897971871784e-12, Test Cost: 3.4979016211300618e-12, MSE Loss: 3.4979016211300618e-12\n",
      "Epoch 1000, Train Cost 1.2333061275796725e-13, Test Cost: 1.2274344951893057e-13, MSE Loss: 1.2274344951893057e-13\n",
      "Epoch 1100, Train Cost 1.1300967892599947e-13, Test Cost: 1.1052407768294067e-13, MSE Loss: 1.1052407768294067e-13\n",
      "Epoch 1200, Train Cost 1.1118676915581813e-13, Test Cost: 1.0977023868867508e-13, MSE Loss: 1.0977023868867508e-13\n",
      "Epoch 1300, Train Cost 1.0974417717895396e-13, Test Cost: 1.0754387696132114e-13, MSE Loss: 1.0754387696132114e-13\n",
      "Epoch 1400, Train Cost 1.0848515418241875e-13, Test Cost: 1.1172314429933744e-13, MSE Loss: 1.1172314429933744e-13\n",
      "Epoch 1500, Train Cost 1.0942622133934543e-13, Test Cost: 1.0684783949537618e-13, MSE Loss: 1.0684783949537618e-13\n",
      "Epoch 1600, Train Cost 1.023721987172474e-13, Test Cost: 1.0031901795815729e-13, MSE Loss: 1.0031901795815729e-13\n",
      "Epoch 1700, Train Cost 9.193676635960157e-14, Test Cost: 9.292037489927116e-14, MSE Loss: 9.292037489927116e-14\n",
      "Epoch 1800, Train Cost 8.466475133819817e-14, Test Cost: 8.023128602457907e-14, MSE Loss: 8.023128602457907e-14\n",
      "Epoch 1900, Train Cost 6.791582677105265e-14, Test Cost: 6.826849740897145e-14, MSE Loss: 6.826849740897145e-14\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fde546a0e48>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "### RNN circle ###\n",
    "\n",
    "import matplotlib.pyplot as plt   \n",
    "import numpy as np\n",
    "\n",
    "\n",
    "print(\"Net trained on constant omega = \", omega)\n",
    "\n",
    "mc_losses = []\n",
    "# define equalizer NN class object\n",
    "net = RNN_linear(data_length, batch_size, learning_rate = 0.01)\n",
    "\n",
    "for epoch in range(epochs):\n",
    "    current_start = epoch*batch_size\n",
    "    data_train_orig_batch = data_train[current_start:(current_start+batch_size),:,:]\n",
    "    start_train_orig_batch = start_train[current_start:(current_start+batch_size),:]   \n",
    "\n",
    "    train_cost = net.train_net(start_train_orig_batch, data_train_orig_batch)\n",
    "\n",
    "    if epoch % 100 == 0: \n",
    "\n",
    "\n",
    "#         (test_cost, test_omega, test_loss_mse, w1, b1) = net.test_net(\n",
    "#             data_test, start_test)\n",
    "        (test_cost, test_est_series, test_loss_mse) = net.test_net(\n",
    "            start_test, data_test)\n",
    "\n",
    "        mc_losses.append(test_cost)\n",
    "\n",
    "\n",
    "        plt.plot(epoch, np.log(test_cost), 'bo')\n",
    "        print('Epoch {}, Train Cost {}, Test Cost: {}, MSE Loss: {}'.format(epoch, train_cost,test_cost, \n",
    "                                                                            test_loss_mse))\n",
    "\n",
    "\n",
    "plt.xlabel('Training Epoch')\n",
    "plt.ylabel('L2 Test Cost')\n",
    "plt.title('NN Equalizer: no noise')\n",
    "# plt.text(1000, .025, r'NN equalizer')\n",
    "# plt.text(0.5, .025, r'Zero Force equalizer')\n",
    "plt.show()\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# print(np.array(test_est_series).shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fde45b5c160>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "data_est = np.array(test_est_series)\n",
    "\n",
    "t = np.linspace(0,np.pi*2,100)\n",
    "plt.plot(np.cos(t), np.sin(t), linewidth=1, color='g')\n",
    "plt.gca().set_aspect('equal', adjustable='box')\n",
    "\n",
    "m = 0 # test number\n",
    "\n",
    "for j in range(0,data_length):\n",
    "    x1 = data_test[m,j,0]\n",
    "    y1 = data_test[m,j,1]\n",
    "    plt.plot(x1,y1,'bo')\n",
    "    \n",
    "    x2 = data_est[m,j,0]\n",
    "    y2 = data_est[m,j,1]\n",
    "    plt.plot(x2,y2,'ro')\n",
    "    \n",
    "#     print(x1-x2, y1-y2)\n",
    "    \n",
    "# plt.plot(x1,y1,'bo')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
